using System;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
using System.Xml;

namespace PropertyExpression.PresentationCode
{
    public static class Property
    {
        public static DataTemplate ToDataTemplate(this object obj)
        {
            return (DataTemplate)
                   XamlReader.Load(
                       XmlReader.Create(
                           new StringReader(
                               string.Format(
                                   @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</DataTemplate>",
                                   XamlWriter.Save(obj)))));
        }

        public static IPropertyProvider<T> C<T>()
        {
            return default(IPropertyProvider<T>);
        }

        public static IPropertyProvider<T> C<T>(this IElement<T> it)
        {
            return C<T>();
        }

        public static IElement<T> New<T>()
        {
            return new ElementImpl<T>(new FrameworkElementFactory(typeof(T)));
        }

        private class ElementImpl<T> : IElement<T>
        {
            private readonly FrameworkElementFactory frameworkElementFactory;

            public IElement<T> Nested(params IElementBase[] elementBases)
            {
                foreach (var elementFactory in elementBases)
                {
                    frameworkElementFactory.AppendChild(elementFactory.FrameworkElementFactory);
                }
                return this;
            }

            public void SetBinding(DependencyProperty dependencyProperty, BindingBase value)
            {
                frameworkElementFactory.SetBinding(dependencyProperty, value);
            }

            public string Name
            {
                get
                {
                    return frameworkElementFactory.Name;
                }
                set
                {
                    frameworkElementFactory.Name = value;
                }
            }

            public FrameworkElementFactory FrameworkElementFactory
            {
                get { return frameworkElementFactory; }
            }

            public ElementImpl(FrameworkElementFactory frameworkElementFactory)
            {
                this.frameworkElementFactory = frameworkElementFactory;
            }

            public void SetValue(DependencyProperty dependencyProperty, object value)
            {
                frameworkElementFactory.SetValue(dependencyProperty, value);
            }
        }
    }
}